'''配置文件（如数据库连接配置）'''

# recommender.py

import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
class Recommender:
    def __init__(self, data):
        """初始化推荐系统"""
        self.data = data
        self.user_product_matrix = self.create_user_product_matrix(data)
        self.product_similarity_matrix = self.calculate_product_similarity(self.user_product_matrix)

    def create_user_product_matrix(self, data):
        """创建用户-商品矩阵"""
        user_product_matrix = pd.pivot_table(
            data, index='username', columns='goods_sn', aggfunc='size', fill_value=0
        )
        return user_product_matrix

    def calculate_product_similarity(self, user_product_matrix):
        """计算商品之间的余弦相似度"""
        similarity_matrix = cosine_similarity(user_product_matrix.T)  # 计算商品之间的余弦相似度
        similarity_df = pd.DataFrame(similarity_matrix, index=user_product_matrix.columns,
                                     columns=user_product_matrix.columns)

        return similarity_df

    def get_top_n_recommendations(self, username=None, top_n=6,threshold=0.5):
        """根据用户购买历史或热门商品推荐商品"""
        if username:
            # 检查该用户是否有购买记录
            if username not in self.user_product_matrix.index:
                # 如果没有购买记录，直接推荐热门商品
                print(f"新用户 {username}，推荐热门商品。")
                return self.get_most_popular_products(top_n)
            # 基于用户的购买历史进行推荐
            purchased_products = self.user_product_matrix.loc[username]
            recommended_products = {}

            # 计算与已购买商品相似的商品
            for product_id in purchased_products[purchased_products > 0].index:
                similar_products = self.product_similarity_matrix[product_id]
                for similar_product, score in similar_products.items():
                    if purchased_products[similar_product] == 0 and score >= threshold:  # 只推荐未购买的商品与相似度大于阈值,新增内容and score >= threshold:
                        if similar_product not in recommended_products:
                            recommended_products[similar_product] = score
                        else:
                            recommended_products[similar_product] += score

            # 根据相似度排序
            recommended_products = sorted(recommended_products.items(), key=lambda x: x[1], reverse=True)
            # 获取排序后的商品数量
            product_count = len(recommended_products)
            print(f"推荐商品数量: {product_count}")
            # 如果推荐商品数量小于 top_n，则补充热门商品
            if product_count < top_n:
                top_m = top_n - product_count  # 计算需要补充的商品数量
                top_recommendations = [product for product, score in recommended_products[:top_n]]
                # 补充热门商品
                popular_products = self.get_most_popular_products(top_m)  # 获取热门商品
                top_recommendations.extend(popular_products)  # 将热门商品添加到推荐列表中
            else:
                # 如果推荐商品数量足够，直接取前 top_n 个商品
                top_recommendations = [product for product, score in recommended_products[:top_n]]
        else:
            # 如果没有提供用户名，推荐热门商品
            top_recommendations = self.get_most_popular_products(top_n)

        return top_recommendations

    def get_most_popular_products(self, top_n=6):
        """获取购买最多的商品"""
        product_counts = self.data['goods_sn'].value_counts()
        popular_products = product_counts.head(top_n).index.tolist()
        return popular_products

